#pragma once

#include <iostream>
#include <string>
#include <functional>
#include <cassert>
#include <cstdlib>
#include <pthread.h>

// .hpp  声明和实现都在这里
// header only 开源代码

namespace mythread
{
    typedef std::function<void *(void *)> func_t; // 或可使用模板，此处为了使其简单，使用void*作为参数类型
    const int size = 1024;

    class Thread
    {
    public:
        Thread()
        {
            // c++
            // _tname = "thread->";
            // _tname += std::to_string(number);

            // 这里使用C语言的接口，是为了增强C接口的使用熟练度，以应对将来可能经常面对的系统编程和网络编程，因为他们提供的接口大多都是C接口
            char namebuffer[size];
            snprintf(namebuffer, sizeof(namebuffer) - 1, "thread-%d", _thread_num++);
            _tname = namebuffer;

            // // 启动线程
            // start();
        }

        // 线程启动
        void start(func_t func, void *args = nullptr)
        {
            _func = func;
            _args = args;
            // int n = pthread_create(&_tid, nullptr, _func, _args);// 此函数是C函数，但function是C++的接口，C语言不识别
            int n = pthread_create(&_tid, nullptr, start_routine, this); // 从这里看出start_routine有且只有一个参数，并接收_args作为参数
            assert(n == 0);                                              // 保证线程创建成功
            /*
            意料之外：使用异常或if
            意料之种：使用assert
            */
            (void)n;
        }

        // 线程等待
        void join()
        {
            int n = pthread_join(_tid, nullptr);
            assert(n == 0); // assert: debug发布的时候存在，release发布时不存在，此时n就是一个被定义但没有被使用的变量，
            // 这样在有的编译器下会报warning
            (void)n; // 这个行为就是告诉编译器，变量n被使用，不要报warning
        }
        std::string thread_name() const
        {
            return _tname;
        }
        ~Thread()
        {
            // do nothinf
        }

    private:
        // void* start_routine(void* args)// 类内成员，还有this指针作为参数
        static void *start_routine(void *args)
        {
            Thread *_this = static_cast<Thread *>(args);
            return _this->run(_this->_args);
        }
        void *run(void *args)
        {
            return _func(args);
        }
    private:
        pthread_t _tid;     // 线程id
        std::string _tname; // 线程名字
        func_t _func;       // 线程执行的函数
        void *_args;        // 线程执行的参数

        static int _thread_num; // 用于线程名字编号
    };
    int Thread::_thread_num = 1;

}